package com.example.yskjproject.utils;

import com.example.yskjproject.helper.SeriaPortHelper;

import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

public class SerialPortUtils {
    private ByteBuffer byteBuffer = ByteBuffer.allocate(1024); // 初始化ByteBuffer
    private int state = 0; // 状态变量，默认为0
    private byte[] header1 = new byte[]{(byte) 0x55, (byte) 0xAA}; // 帧头1
    private byte[] header2 = new byte[]{(byte) 0x65, (byte) 0xAA}; // 帧头2
    private byte[] headerBuffer = new byte[2]; // 缓存帧头
    private int headerIndex = 0; // 记录帧头缓存的位置
    private static final int ERROR_STX_ETX = -1;
    private static final int ERROR_CRC = -2;
    private static final int ERROR_LENGTH = -3;

    public Map<String, String> receiveSerialMsg(String msg) {
        Map<String, String> outputMap = new HashMap<>();
        try {
            byte[] receiveBytes = hexStr2bytes(msg);
            byteBuffer.put(receiveBytes);
            byteBuffer.flip(); // 翻转ByteBuffer以便读取
            int headerStartPosition = 0;
            while (byteBuffer.hasRemaining()) { // 确保有数据可以处理
                byte currentByte = byteBuffer.get();

                switch (state) {
                    case 0: // 寻找帧头
                        if (headerIndex < header1.length && (header1[headerIndex] == currentByte || header2[headerIndex] == currentByte)) {
                            headerBuffer[headerIndex++] = currentByte;
                            if (headerIndex == header1.length) {
                                state = 1; // 检测到帧头
                                headerIndex = 0; // 重置帧头索引
                                // 记录帧头的起始位置
                                headerStartPosition = byteBuffer.position() - header1.length;
                            }
                        } else {
                            headerIndex = 0; // 未匹配到帧头，重置索引
                            continue;
                        }
                        break;
                    case 1: // 已找到帧头，处理数据包
                        // 回到帧头的起始位置
                        byteBuffer.position(headerStartPosition);
                        byte[] effectiveBytes = new byte[20]; // 帧头2字节 + 数据11字节 + 校验和1字节
                        byteBuffer.get(effectiveBytes, 0, 20);

                        outputMap = dealEffectiveBytes(effectiveBytes);
                        state = 0; // 处理完数据包后重置状态
                        break;
                    default:
                        break;
                }
            }
            byteBuffer.compact(); // 清除已读取的数据
        } catch (Exception e) {
            e.printStackTrace();
        }
        return outputMap;
    }

    private Map<String, String> dealEffectiveBytes(byte[] effectiveBytes) {
        Map<String, String> outputMap = new HashMap<>();
        return dataParser(effectiveBytes, outputMap);
    }

    public byte[] hexStr2bytes(String hex) {
        int len = (hex.length() / 2);
        byte[] result = new byte[len];
        char[] achar = hex.toUpperCase().toCharArray();
        for (int i = 0; i < len; i++) {
            int pos = i * 2;
            result[i] = (byte) (hexChar2byte(achar[pos]) << 4 | hexChar2byte(achar[pos + 1]));
        }
        return result;
    }

    private static byte hexChar2byte(char c) {
        if (c >= '0' && c <= '9') {
            return (byte) (c - '0');
        } else if (c >= 'A' && c <= 'F') {
            return (byte) (c - 'A' + 10);
        } else if (c >= 'a' && c <= 'f') {
            return (byte) (c - 'a' + 10);
        }
        throw new IllegalArgumentException("Invalid hexadecimal character: " + c);
    }

    // 检查CRC校验
    private boolean checkCRC(byte[] data) {
        // 假设CRC8校验和位于数组的最后一个字节
        int crcCalculated = SeriaPortHelper.crc8(Arrays.copyOfRange(data, 0, data.length - 1));
        int crcReceived = data[data.length - 1] & 0xFF;
        return crcCalculated == crcReceived;
    }


    // 字节转十六进制字符串
    private String byte2hex(byte[] b) {
        StringBuilder sb = new StringBuilder(b.length * 2);
        for (byte aB : b) {
            int v = aB & 0xFF;
            if (v < 16) {
                sb.append('0');
            }
            sb.append(Integer.toHexString(v));
        }
        return sb.toString().toUpperCase();
    }

    // 指令中业务参数解析
    private Map<String, String> dataParser(byte[] data, Map<String, String> outputMap) {
        // 校验帧头
        if (!(data[0] == (byte) 0x65 && data[1] == (byte) 0xAA) && !(data[0] == (byte) 0x55 && data[1] == (byte) 0xAA)) {
            return null;
        }
        // 校验CRC
        if (!checkCRC(data)) {
            return null;
        }
        // 校验长度
        if (data.length != 20) {
            return null;
        }

        byte length = data[2];
        // 解析数据
        byte enable = data[3]; // 使能状态
        byte force = data[4]; // 力量反馈
        byte zeroPoint = data[5]; // 零点重置
        byte status = data[6]; // 模式状态
        short position = (short) (((data[7] & 0xFF) << 8) + (data[8] & 0xFF)); // 数据反馈
        short speed = (short) (((data[9] & 0xFF) << 8) + (data[10] & 0xFF)); // 速度反馈
        short powerFeedback = (short) (((data[11] & 0xFF) << 8) + (data[12] & 0xFF)); // 功率反馈
        byte fault = data[13]; // 故障
        byte releaseForce = data[14]; // 安全泄力保护
        byte communicationError = data[15]; // 主板通信异常
        byte[] reserved = new byte[3]; // 备用字段
        System.arraycopy(data, 16, reserved, 0, 3);
        int checksum = (data[19] & 0xFF); // 校验和

        // 将数据放入Map
        outputMap.put("FRAME_HEADER", byte2hex(new byte[]{data[0], data[1]}));
        outputMap.put("LENGTH", Integer.toString(length & 0xFF));
        outputMap.put("ENABLE", Integer.toString(enable & 0xFF));
        outputMap.put("FORCE", Integer.toString(force & 0xFF));
        outputMap.put("ZERO_POINT", Integer.toString(zeroPoint & 0xFF));
        outputMap.put("STATUS", Integer.toString(status & 0xFF));
        outputMap.put("POSITION", Integer.toString(position));
        outputMap.put("SPEED", Integer.toString(speed));
        outputMap.put("POWER_FEEDBACK", Integer.toString(powerFeedback));
        outputMap.put("FAULT", Integer.toString(fault & 0xFF));
        outputMap.put("RELEASE_FORCE", Integer.toString(releaseForce & 0xFF));
        outputMap.put("COMMUNICATION_ERROR", Integer.toString(communicationError & 0xFF));
        outputMap.put("RESERVED", byte2hex(reserved));
        outputMap.put("CHECKSUM", Integer.toString(checksum & 0xFF));
        outputMap.put("ZERO_COMBINATION",byte2hex(new byte[]{data[0], data[1]}) + (zeroPoint & 0xFF));
        outputMap.put("POSITION_COMBINATION", byte2hex(new byte[]{data[0], data[1]}) + (position & 0xFFFF));

        return outputMap;
    }

    // 将两个字节转换为整数
    private int bytesToInt(byte[] bytes) {
        return (bytes[0] & 0xFF) << 8 | (bytes[1] & 0xFF);
    }
}
